﻿using MiniFox.Components;
using MiniFox.Infrastructure;
using MiniFox.Platform.Exceptions;
using MiniFox.Platform.File.Models;
using MiniFox.Platform.File.Providers;
using MiniFox.Utility;

namespace MiniFox.Platform.File.Services
{
    /// <summary>
    /// 文件读取
    /// </summary>
    public abstract class FileService : FileSystemBase, IFileService
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="group"></param>
        protected FileService(string group) : base(group)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        [AutoWired]
        protected IFileProvider Provider { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        public void CheckFileAvaliable(CheckFileRequest request)
        {
            var fileData = Provider.GetFile(this.Group, request.Path, request.FileName);
            if (fileData != null)
            {
                throw new PlatformException("ERR_OperateFail");
            }
        }
        #region load
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileData"></param>
        protected abstract void OnLoad(FileData fileData);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileId"></param>
        /// <returns></returns>
        public virtual FileData Load(string fileId)
        {
            FileData fileData = GetFileDatasFromCache(fileId);
            if (fileData == null)
            {
                fileData = Provider.GetFile(fileId);
                if (fileData != null)
                {
                    OnLoad(fileData);
                    SetFileDataToCache(fileData);
                }
            }
            return fileData;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileData"></param>
        protected abstract Task OnLoadAsync(FileData fileData);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileId"></param>
        /// <returns></returns>
        public virtual async Task<FileData> LoadAsync(string fileId)
        {
            FileData fileData = GetFileDatasFromCache(fileId);
            if (fileData == null)
            {
                fileData = Provider.GetFile(fileId);
                if (fileData != null)
                {
                    await OnLoadAsync(fileData);
                    SetFileDataToCache(fileData);
                }
            }
            return fileData;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileIds"></param>
        /// <returns></returns>
        public virtual IEnumerable<FileData> LoadBatch(string[] fileIds)
        {
            var list = new List<FileData>();
            Parallel.ForEach(fileIds, fileId =>
            {
                list.Add(Load(fileId));
            });
            return list;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileIds"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<FileData>> LoadBatchAsync(string[] fileIds)
        {
            var list = new List<FileData>();
            await Parallel.ForEachAsync(fileIds, async (fileId, cancelToken) =>
            {
                var fileData = await LoadAsync(fileId);
                list.Add(fileData);
            });
            return list;
        }
        #endregion

        #region query file 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileIds"></param>
        /// <returns></returns>
        public virtual IEnumerable<FileData> Query(string[] fileIds)
        {
            var list = new List<FileData>();
            Parallel.ForEach(fileIds, fileId =>
            {
                var fileData = GetFileDatasFromCache(fileId);
                if (fileData == null)
                    fileData = Provider.GetFile(fileId);
                list.Add(fileData);
            });
            return list;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public virtual FileData[] GetFiles(string path, int? top = 100)
        {
            path = string.IsNullOrWhiteSpace(path) ? "/": path.Trim();
            if (path != "/")
                path = $"/{path.Trim('/')}/";
            var fileDatas = this.Provider.Query(this.Group, path, top);
            return fileDatas;
        }

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="folderId"></param>
        ///// <returns></returns>
        //public virtual IEnumerable<FileData> Query(string folderId)
        //{
        //    var fileDatas = this.Provider.Query(folderId);
        //    return fileDatas;
        //}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="queryObject"></param>
        /// <returns></returns>
        public virtual ResultObject<IEnumerable<FileData>> Query(PagedQueryObject<FileQuery> queryObject)
        {
            if (queryObject.Parameters.Path != "/")
                queryObject.Parameters.Path = $"/{queryObject.Parameters.Path.Trim('/')}/";
            return Provider.Query(this.Group, queryObject);
        }

        #endregion

    }

}
